package com.specialized.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.diagnosis.DiagnosisUtils;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.specialized.common.core.exception.ServiceException;
import com.specialized.common.core.utils.StringUtils;
import com.specialized.common.redis.service.RedisService;
import com.specialized.passenger.domain.User;
import com.specialized.pay.Payutils.AlipayUtils;
import com.specialized.pay.domain.Pickairport;
import com.specialized.pay.domain.RealTime;
import com.specialized.pay.domain.Trade;
import com.specialized.pay.mapper.RealTimeMapper;
import com.specialized.pay.service.ITradeService;
import com.specialized.pay.service.PayService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author：wangxinyu
 * @Package：com.specialized.pay.service.impl
 * @Project：Specialized-Cloud
 * @name：PayServiceImpl
 * @Date：2024/7/19 19:09
 */
@Service("zfb")
@Primary
public class ZfbPayServiceImpl implements PayService {

    private final ApplicationEventPublisher applicationEventPublisher;

    public ZfbPayServiceImpl(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }


    @Autowired
    private  RedisService redisService;
    @Autowired
    private ITradeService tradeService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RealTimeMapper realTimeMapper;



    /**
     * 下单支付接口
     * @param orderCard
     * @return
     */

    @Override
    public String alipayTradePagePay(String orderCard) throws AlipayApiException {
        String[] order = orderCard.split("_");
        //同笔订单，不同设备同时发送
        RLock lock = redissonClient.getLock(order[0]);
        try {
            boolean tryLock = lock.tryLock();
            if (!tryLock) {
                throw new ServiceException("锁被占用");
            }
            lock.lock(5, TimeUnit.MINUTES);
            Trade trade = new Trade();
            trade.setOrderCard(order[0]);
            trade.setPaytype(Long.valueOf(order[1]));
            //判断当前当前正在执行中的/成功的//(解决当前订单一直正在执行中的问题 根据商户订单号去查询，闪退
//            trade.setStatus(1L);
            List<Trade> tradesList = tradeService.selectTradeList(trade);
            if (!tradesList.isEmpty()) {
                for (Trade trade1 : tradesList) {
                    if (trade1.getStatus() == 2L) {
                        throw new ServiceException("重复支付");
                    }
                    if (trade1.getStatus() == 1L) {
                        String alipaystatus= alipayTradeQuery(trade1.getOuttradeno());
                        if ("TRADE_SUCCESS".equals(alipaystatus)) {
                            throw new ServiceException("当前支付成功");
                        }
                    }
                }
            }
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayUtils.getAlipayConfig());
            // 构造请求参数以调用接口
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
//            if ("1".equals(order[1])) {
//                trade.setSubject("预约订单");
//                trade.setTotalamount(new BigDecimal("88.88"));
//            }
            if ("2".equals(order[1])) {
                trade.setSubject("实时订单");
                //查询点单号对应订单
                RealTime realTime = realTimeMapper.selRealTimeBbyOrderCard(trade.getOrderCard());
                if (StringUtils.isBlank(realTime.toString())){
                    throw new ServiceException("订单号:"+order[0]+"对应订单不存在");
                }
                trade.setTotalamount(realTime.getRealPrice());
            }
            if ("3".equals(order[1])) {
                trade.setSubject("接机订单");
                Pickairport pickairport = realTimeMapper.selPickairportBbyOrderCard(trade.getOrderCard());
                if (StringUtils.isBlank(pickairport.toString())){
                    throw new ServiceException("订单号:"+order[0]+"对应订单不存在");
                }
                trade.setTotalamount(pickairport.getRealPrice());
            }
//            if ("4".equals(order[1])) {
//                trade.setSubject("送机订单");
//                trade.setTotalamount(new BigDecimal("88.88"));
//            }
//            if ("5".equals(order[1])) {
//                trade.setSubject("包车订单");
//                trade.setTotalamount(new BigDecimal("88.88"));
//            }
            //生成商户订单号
            String outTradeNo = UUID.randomUUID().toString();
            trade.setStatus(1L);
            trade.setCreattime(new Date());
            trade.setOuttradeno(outTradeNo);
            trade.setCreatby("1");
            trade.setProductcode("FAST_INSTANT_TRADE_PAY");
            tradeService.insertTrade(trade);
            // 设置订单标题
            model.setSubject(trade.getSubject());
            // 设置产品码
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            // 设置商户订单号
            model.setOutTradeNo(trade.getOuttradeno());
            // 设置订单总金额
            model.setTotalAmount(String.valueOf(trade.getTotalamount()));
            request.setNotifyUrl(AlipayUtils.NOTIFY_URL);
            request.setBizModel(model);
            // 第三方代调用模式下请设置app_auth_token
            // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
            //异步回调
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
            // 如果需要返回GET请求，请使用
            // AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "GET");
            if (response.isSuccess()) {
                System.out.println("支付调用成功");
                String pageRedirectionData = response.getBody();
                System.out.println(pageRedirectionData);


                return pageRedirectionData;
            }else {
                System.out.println("支付调用失败");
//                 sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                System.out.println(diagnosisUrl);
            }
            return "支付异常";
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            lock.forceUnlock();
        }

    }

    /**
     * 交易关闭
     * @param tradeNo 交易流水号
     * @throws AlipayApiException
     */
    @Override
    public void closeAlipayTradePagePay(String tradeNo) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayUtils.getAlipayConfig());
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("trade_no", tradeNo);
        request.setBizContent(bizContent.toString());
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }

    }
    /**
     * 交易退款
     * @param tradeNo
     * @throws AlipayApiException
     */
    @Override
    public void alipayTradeRefund(String tradeNo) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayUtils.getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();

//        // 设置商户订单号
//        model.setOutTradeNo("20150320010101001");
        // 设置支付宝交易号
        model.setTradeNo(tradeNo);
        //根据订单号查询交易金额
        // 设置退款金额
        model.setRefundAmount("88.88");
        // 设置退款原因说明
        model.setRefundReason("正常退款");
        // 设置针对账期交易
//        model.setRelatedSettleConfirmNo("2024041122001495000530302869");
        // 设置退款请求号
        model.setOutRequestNo("HZ01RF001");
        request.setBizModel(model);
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
             String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
             System.out.println(diagnosisUrl);
        }


    }
    /**
     * 交易查询接口
     * @param outTradeNo
     * @throws AlipayApiException
     */
    @Override
    public String alipayTradeQuery(String outTradeNo) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayUtils.getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();

        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo(outTradeNo);
        request.setBizModel(model);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        Trade trade = new Trade();
        trade.setUpdatetime(new Date());
        if (response.isSuccess()) {
            System.out.println("查询调用成功");
            System.out.println(response.getBody());

            String tradeNo = response.getTradeNo();
            String tradeStatus = response.getTradeStatus();
            String totalAmount = response.getTotalAmount();


            trade.setStatus(2L);
            trade.setTradeno(tradeNo);
            trade.setPaymoney(new BigDecimal(totalAmount));
            trade.setOuttradeno(outTradeNo);
            if (!"TRADE_SUCCESS".equals(tradeStatus)) {
                //关闭交易
                closeAlipayTradePagePay(outTradeNo);
                trade.setStatus(3L);
            }
            //        修改


            //查询当前支付流水记录
            Trade trade1 = tradeService.selectTradeByoutTradeNo(outTradeNo);
            User user = new User();
            if (2==trade1.getPaytype()) {
                //修改当前订单支付状态
                RealTime realTime = realTimeMapper.selRealTimeBbyOrderCard(trade1.getOrderCard());
                realTime.setOrderCard(trade1.getOrderCard());
                realTime.setOrderStatus(5L);
                realTime.setEndTime(trade1.getUpdatetime());
                realTimeMapper.updReadTime(realTime);
                user.setUserId(realTime.getUserId());

            }
            if (3==trade1.getPaytype()) {
                //修改当前订单支付状态
                Pickairport pickairport = realTimeMapper.selPickairportBbyOrderCard(trade1.getOrderCard());
                pickairport.setOrderCard(trade1.getOrderCard());
                pickairport.setOrderStatus(5L);
                pickairport.setEndTime(trade1.getUpdatetime());
                realTimeMapper.updPickairport(pickairport);
                user.setUserId(pickairport.getUserId());

            }

            int userScour = trade1.getTotalamount().intValue() * 100;
            user.setUserScore(Long.valueOf(userScour));

            if (trade1.getStatus()==1){

                applicationEventPublisher.publishEvent(user);
            }
            int i = tradeService.updateTrade(trade);
            return tradeStatus;
        }else {
            System.out.println("查询调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
//            String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
//            System.out.println(diagnosisUrl);
            //修改当前订单号的状态为关闭
            trade.setStatus(3L);
            trade.setOuttradeno(outTradeNo);
            int i = tradeService.updateTrade(trade);

        }

        return "FAILE";
    }
    /**
     * 交易退款查询
     * @param tradeNo
     * @throws AlipayApiException
     */
    @Override
    public String alipayTradeFastpayRefundQuery(String tradeNo) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayUtils.getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();

        // 设置商户订单号
//        model.setOutTradeNo("2014112611001004680073956707");


        // 设置支付宝交易号
        model.setTradeNo(tradeNo);

        // 设置退款请求号
        model.setOutRequestNo("HZ01RF001");

        request.setBizModel(model);
        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        String refundStatus = response.getRefundStatus();
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
             String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
             System.out.println(diagnosisUrl);
        }
        return refundStatus;
    }

    /**
     * 异步回调
     * @param request
     * @return
     * @throws AlipayApiException
     */

    @Override
    public String notifyUrl(HttpServletRequest request) throws AlipayApiException {
//        log.info("异步通知开始");
        Map<String, String> map =AlipayUtils.getStringStringMap(request);
        //调用SDK验证签名
        boolean signVerified = false;
        try {
            AlipayConfig alipayConfig = AlipayUtils.getAlipayConfig();
            signVerified = AlipaySignature.rsaCheckV1(map, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!signVerified) {
            return "failure";
        }
        System.out.println("支付结果---：" + map.toString());
        Trade trade = new Trade();
        //商户订单号
        String outTradeNo = map.get("out_trade_no");

        trade.setOuttradeno(outTradeNo);
        trade.setStatus(1L);
        //查询当前订单是否已经被回调过
        List<Trade> trades = tradeService.selectTradeList(trade);
        if(trades.size()<=0){
            throw new ServiceException("重复回调");
        }
        String tradeNo = map.get("trade_no");
        String receiptAmount = map.get("receipt_amount");
        //根据交易流水号查询交易信息

        //交易成功
        String tradeStatus = map.get("trade_status");
        //封装对象，修改当前的交易流水的状态
        trade.setTradeno(tradeNo);
        trade.setUpdatetime(new Date());
        trade.setStatus(2L);
        trade.setPaymoney(new BigDecimal(receiptAmount));
        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
            //关闭交易
            closeAlipayTradePagePay(outTradeNo);
            trade.setStatus(3L);
        }
        //查询当前支付流水记录
        Trade trade1 = tradeService.selectTradeByoutTradeNo(outTradeNo);
        User user = new User();
        if (2==trade1.getPaytype()) {
            //修改当前订单支付状态
            RealTime realTime = realTimeMapper.selRealTimeBbyOrderCard(trade1.getOrderCard());
            realTime.setOrderCard(trade1.getOrderCard());
            realTime.setOrderStatus(5L);
            realTime.setEndTime(trade1.getUpdatetime());
            realTimeMapper.updReadTime(realTime);
            user.setUserId(realTime.getUserId());

        }
        if (3==trade1.getPaytype()) {
            //修改当前订单支付状态
            Pickairport pickairport = realTimeMapper.selPickairportBbyOrderCard(trade1.getOrderCard());
            pickairport.setOrderCard(trade1.getOrderCard());
            pickairport.setOrderStatus(5L);
            pickairport.setEndTime(trade1.getUpdatetime());
            realTimeMapper.updPickairport(pickairport);
            user.setUserId(pickairport.getUserId());

        }

        int userScour = trade1.getTotalamount().intValue() * 100;
        user.setUserScore(Long.valueOf(userScour));
        applicationEventPublisher.publishEvent(user);

        //数据处理
        int i = tradeService.updateTrade(trade);
        //添加积分

        return "success";
    }







}
